home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / util / shell / shtml.lha / shtml.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-02  |  7.6 KB  |  265 lines

  1. // CMU96
  2. // .html to .txt converter.
  3.  
  4. // Supplied 'as is'
  5. // NO WARRENTY INCLUDED!
  6. // If this code doesn't do what you expect, sorry, but it isn't my fault!
  7. // It isn't likley to be damaging but there is a small chance I've overlooked
  8. // something. It works for me though.
  9.  
  10. // Compiled with SAS/C compiler.
  11. // I can't garantee this compiling with anything else but it should be about
  12. // 95% portable across Amiga, PC and Unix systems.
  13.  
  14. /*
  15. ** One day, it might...
  16. **
  17. ** remove all unknown tags.
  18. ** cat from and to files.
  19. ** have command line switches and intelligence.
  20. ** do clever stuff with word wrap and line wrap etc.
  21. ** have adjustable margins/tab spaces etc.
  22. ** recognise <br> <p>PARAGRAPH</p> <a href>INVERT</a> <center>CENTER</center>
  23. **           <h?>PARAGRAPH</h?> <blink>UNDERLINE</blink> <title>TITLE\n</title>
  24. **           <pre>PREFORMATTED</pre> <!-- Commemt <br> stuff -->
  25. */
  26.  
  27. // But I doubt it...
  28.  
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32.  
  33. #define width 77
  34.  
  35. void getword(char *word,FILE *in);
  36. int preprocess(char *word,FILE *in,FILE *out,int x,int pure);
  37. int tag(char *word);
  38. int tagis(char *word,char *check);
  39.  
  40. main(int argc,char *argv[])
  41. {
  42.   FILE *in,*out;
  43.   char word[width];
  44.   int argin=1,argout=2,pure=0;
  45.  
  46.   int x=0; // THE X Value (distance from left edge of line in characters)
  47.  
  48.   // Check for correct arguements. If bad, report usage
  49.   if ((argc<2) || (argc>4) || (strcmp(argv[1],"?")==0))
  50.   {
  51.     printf("Usage: %s (-h|-help)|([-p|-pure] infile.html [outfile.txt])\n"
  52.                                                                     ,argv[0]);
  53.     exit(0);
  54.   }
  55.  
  56.   // Check for -help flag
  57.   if ((strcmp(argv[1],"-help")==0) || (strcmp(argv[1],"-h")==0))
  58.   {
  59.     printf("\n");
  60.     printf("%s by Chris Underwood. Compiled with SAS/C. CMU",argv[0]);
  61.     puts("\n");
  62.     puts("Converts .html files into a readable form for displaying in a text");
  63.     puts("only shell. An outfile may be specified or the produced text can be");
  64.     puts("redirected or piped.");
  65.     puts("Options:");
  66.     puts(" -h -help\tPrints this text");
  67.     puts(" -p -pure\tSurpress any non-ascii output (inverse text etc)");
  68.     puts(" infile\t\tSource html file (.html)");
  69.     puts(" outfile\tDestination file (.txt)");
  70.     puts("If no outfile is specified then text output will be sent to stdout.");
  71.     puts("If outfile exists it will be overwritten.");
  72.     puts("This program is supplied \'as is\' and has absolutly no warrenty");
  73.     puts("whatsoever. If it (unlikely) screws up your HD, it \'aint my fault!");
  74.     printf("\n");
  75.     exit(0);
  76.   }
  77.  
  78.   // Check for pure flag, and adjust where to expect *in and *out in the
  79.   // arguement list.
  80.   if ((strcmp(argv[1],"-p")==0) || (strcmp(argv[1],"-pure")==0))
  81.   {
  82.     argin=2;  // Set in and out args
  83.     argout=3;
  84.     pure=1;   // Set pure flag
  85.   }
  86.   
  87.   // Open infile and check to see if it exists. Give error if necessary.
  88.   if ((in=fopen(argv[argin],"r"))==NULL)
  89.   {
  90.     fprintf(stderr,"%s: Failed to open file %s for reading\n",
  91.                                                        argv[0],argv[argin]);
  92.     exit(1);
  93.   }
  94.  
  95.   // Similar check and open outfile.
  96.   if (argc==argout+1)
  97.   {
  98.     if ((out=fopen(argv[argout],"w"))==NULL)
  99.     {
  100.       fprintf(stderr,"%s: Failed to open file %s for writing\n",
  101.                                                        argv[0],argv[argout]);
  102.       exit(1);
  103.     }
  104.   } else {
  105.     // Set out to be pointing at stdout. Somehow, this actually works!
  106.     out=stdout;
  107.   }
  108.  
  109.   // Main processing loop
  110.   while (!feof(in)) // Better check for eof alot...
  111.   {
  112.     getword(word,in);
  113.     if (tag(word)) x=preprocess(word,in,out,x,pure); else
  114.     {
  115.       if (x+strlen(word)+1<width)  // If word fits on line...
  116.       {
  117.         x+=strlen(word)+1;         // Update the X value
  118.         fprintf(out,"%s ",word);   // And print the word (with space)
  119.       }
  120.       else
  121.       {
  122.         x=strlen(word)+1;          // Reset the X value
  123.         fprintf(out,"\n%s ",word); // And print the word on a new line
  124.       }
  125.     }
  126.   }
  127.  
  128.   // Cleanup, close files then exit.
  129.   if (!pure)
  130.   {
  131.     fprintf(out,"%c0m\n",155); // Print a newline and set normal text
  132.   }
  133.   else
  134.   {
  135.     fprintf(out,"\n"); // Shouldn't set normal text here - code is impure
  136.   }
  137.   fclose(in);
  138.   fclose(out);
  139.   exit(0); // Successful conversion from html to txt!
  140. }
  141.  
  142. void getword(char *word,FILE *in)
  143. {
  144.   int j,k,ch;
  145.   j=0;
  146.   for (k=0; k<width; k++) word[k]='\0'; // Like strnset(), except this works.
  147.   word[0]=getc(in);
  148.   // Remove leading spaces
  149.   while (((word[0]==' ') || (word[0]=='\n') || (word[0]=='\t')) && !feof(in))
  150.     word[0]=getc(in);
  151.   if (word[0]=='<') // Tag found.
  152.   {
  153.     k=1; // Start paranthesis count
  154.     while (!feof(in)) // Better be safe now...
  155.     {
  156.       j++;
  157.       if (j==width) j--; // Simple fix suggested by Xav (cheers).
  158.                          // Not very neat, but it works since only comment
  159.                          // tags and bad-html have tags this long
  160.       word[j]=getc(in);
  161.       if (word[j]=='<') k++; // Like a stack, but with no data!
  162.       if (word[j]=='>') k--;
  163.       if (k==0) break; // Angle brackets are now matched
  164.     }
  165.   }
  166.   else // Not a tag - a normal word.
  167.   {
  168.     // Get the word
  169.     while (!feof(in))          // While not eof
  170.     {
  171.       ch=getc(in);
  172.       if (ch==' ')  break;     // And not a space...
  173.       if (ch=='\n') break;     // And not a newline...
  174.       if (ch=='\t') break;     // And not a tab charecter...
  175.       if (j==width) break;     // And not the max width of a word...
  176.       if (ch=='<')
  177.       {
  178.         ungetc(ch,in);
  179.         break;
  180.       }
  181.       j++;
  182.       word[j]=ch;              // Attach ch to the end of word[]
  183.     }
  184.   if (feof(in)) word[0]='\0';
  185.   }
  186. }
  187.  
  188. int preprocess(char *word,FILE *in,FILE *out,int x,int pure)
  189. {
  190.   char smallbuffer[7]; // Used to detect </pre> tag
  191.   int j;
  192.  
  193.   if (tagis(word,"br") || tagis(word,"h") || tagis(word,"p") ||
  194.       tagis(word,"/h") || tagis(word,"/p"))
  195.   {
  196.     fprintf(out,"\n");    // Print a newline
  197.     x=0;                  // Set the X value to the start of the line
  198.   }
  199.  
  200.   if (!pure) // If we are not giving pure output...
  201.   {
  202.     if (tagis(word,"title") || tagis(word,"a") || tagis(word,"blink"))
  203.     {
  204.       fprintf(out,"%c7m",155); // Set inverted text
  205.     }
  206.  
  207.     if (tagis(word,"/title") || tagis(word,"/a") || tagis(word,"/blink"))
  208.     {
  209.       fprintf(out,"%c0m",155); // Set normal text and print a newline
  210.       fprintf(out,"\b ");
  211.     }
  212.   }
  213.  
  214.   if (tagis(word,"/title")) // We need a newline...
  215.   {
  216.     x=0;
  217.     fprintf(out,"\n");
  218.   }
  219.  
  220.   if (tagis(word,"pre")) // Sort this here. Should be a function but I'm lazy!
  221.   {
  222.     smallbuffer[6]='\0'; // So that strcmp() works.
  223.     printf("\n");
  224.     x=0; // After the </pre> tag we will print a newline
  225.     for (j=0; (j<6) && !feof(in); j++) // Fill the small buffer
  226.     {
  227.       smallbuffer[j]=fgetc(in);
  228.     }
  229.     while(!feof(in) && !(strcmp(smallbuffer,"</pre>")==0))
  230.     {
  231. //fprintf(stderr,"%s\n",smallbuffer);
  232.       // Print first buffer char
  233.       fprintf(out,"%c",smallbuffer[0]);
  234.       // Shuffle buffer left
  235.       for (j=1; j<6; j++) smallbuffer[j-1]=smallbuffer[j];
  236.       // Get a new char
  237.       smallbuffer[5]=fgetc(in);
  238.     }
  239.     // Exit conditions checked by while loop
  240.     // No need to dump the small buffer because it only contains </pre> anyway
  241.     printf("\n");
  242.   }
  243.  
  244.   return x;
  245. }
  246.  
  247. int tagis(char *word,char *check)
  248. {
  249.   int same=1,j;
  250.   for (j=0; j<strlen(check); j++) // Walk through check string
  251.   {
  252.     if (word[j+1] != check[j]) // If we have unequal charecters...
  253.     {
  254.       same=0; // State the inequality
  255.       break;  // Not much point in continuing now...
  256.     }
  257.   }
  258.   return same; // And send back the result
  259. }
  260.  
  261. int tag(char *word)
  262. {
  263.   if (word[0]=='<') return 1; else return 0;
  264. }
  265.